
#include "include/gtest.h"
#include "../Tool/include/EventLoop.h"
#include "../Tool/include/ILogger.h"
#include <type_traits>

namespace Tool
{

/*
 * 判断类型
*/
template<typename T>
constexpr bool is_number_v = false;

template<>
constexpr bool is_number_v<int> = true;

template<>
constexpr bool is_number_v<float> = true;

template<>
constexpr bool is_number_v<double> = true;

template<typename T>
bool is_string_v = false;

template<>
bool is_string_v<std::string> = true;

template<typename T>
constexpr bool is_pointer_v = false;

template<typename T>
constexpr bool is_pointer_v<T*> = true;

template<typename T>
constexpr bool is_pointer_v<T* const> = true;

template<typename T>
constexpr bool is_pointer_v<const T*> = true;

template<typename T>
struct SignedBase
{
    static constexpr bool Signed = false;
    static constexpr bool UnSigned = true;
};

template<>
struct SignedBase<int>
{
    static constexpr bool Signed = true;
};

template<>
struct SignedBase<char>
{
    static constexpr bool Signed = true;
};

template<>
struct SignedBase<float>
{
    static constexpr bool Signed = true;
};

template<>
struct SignedBase<unsigned int>
{
    static constexpr bool UnSigned = true;
};

template<>
struct SignedBase<unsigned char>
{
    static constexpr bool UnSigned = true;
};

template<typename T>
constexpr bool is_signed_v = SignedBase<T>::Signed;

template<typename T>
constexpr bool is_unsigned_v = SignedBase<T>::UnSigned;


/*
 * 构建void
*/

template<typename... T> struct make_void
{
    using type = void;
};

template<typename... T>
using void_t = typename make_void<T...>::type;

/*
 * 检查是否有某个函数
*/
template<typename T, typename = void>
struct has_size_returning_size_t : std::false_type {};

template<typename T>
struct has_size_returning_size_t<T, std::void_t<decltype(std::declval<T>().size())>>
    : std::is_same<decltype(std::declval<T>().size()), size_t> {};

template<typename T>
auto PrintSize(T &t) -> std::enable_if_t<has_size_returning_size_t<T>::value, void>
{
    LOG_INFO("size: %zu", t.size());
}

template<typename T>
auto PrintSize(T &t) -> std::enable_if_t<!has_size_returning_size_t<T>::value, void>
{
    LOG_INFO("No size() member");
}

template<typename T, typename = void>
struct has_size : std::false_type{};

//匹配特列化模板
template<typename T>
struct has_size<T, std::void_t<decltype(std::declval<T>().size(), void())>> : std::true_type{};

struct Test
{
    Test() = default;
    Test(size_t s)
    {
        _size = s;
    }
    size_t size()
    {
        return _size;
    }
    size_t _size = 100;
};

struct Test1
{
    size_t _size = 100;
};


/*
 * 编译期多态，零虚函数开销
*/
template<typename T>
struct Comparable
{
    friend bool operator>(const T &a, const T &b)
    {
        return a.value() > b.value();
    }
    friend bool operator<(const T &a, const T &b)
    {
        return a.value() < b.value();
    }
};

struct IntWrapper : Comparable<IntWrapper>
{
    int val;
    int value() const //只有标记为const 才能被const对象调用
    {
        return val;
    }
    IntWrapper(int a)
        :val(a)
    {

    }
};


/*
 * 折叠表达式
*/
template<typename... Args>
auto Sum(Args... args)
{
    return (args + ...);
}


/*
 * 模板递归，编译器计算函数
*/
template<int N>
struct Factorial
{
    static constexpr int value = N + 2 - 5;
};

template<>
struct Factorial<0>
{
    static constexpr int value = 1;
};

TEST(CodeTest, CodeTestTest)
{

    int _A = 10;
    constexpr int x = 20;
    constexpr int y = x + 2;
    constexpr unsigned int z = 20;
    std::string a = "hellow";
//    constexpr std::string b = "world";
    //    std::vector<const int> a;
//    LOG_INFO("is number %d", is_number_v<_A>);
    LOG_INFO("is number %d", is_number_v<decltype(_A)>);
    LOG_INFO("is number %d", is_number_v<std::string>);
    LOG_INFO("is pointer %d", is_pointer_v<std::string*>);
    LOG_INFO("is pointer %d", is_pointer_v<decltype(_A)>); //is_pointer_v需要编译器推导类型，decltype可以获取变量的编译器类型
    LOG_INFO("is string %d", is_string_v<std::string*>);
    LOG_INFO("is string %d", is_string_v<decltype(a)>);
    LOG_INFO("is string %d", is_string_v<std::string>);

    LOG_INFO("is signed %d", is_signed_v<std::string>);
    LOG_INFO("is signed %d", is_signed_v<decltype(a)>);
    LOG_INFO("is signed %d", is_unsigned_v<decltype(z)>);

    Test b;
    Test1 c;
    PrintSize(a);   //自动推导传入参数类型，等价于 PrintSize<std::string>(a);
    PrintSize(b);
    PrintSize(c);

    IntWrapper d(10),e(20);
    LOG_INFO("a > b: %d", d > e);
    LOG_INFO("a < b: %d", d < e);

    LOG_INFO("sum: %.2f", Sum(2, 12.2, 5));
    LOG_INFO("sum: %d", Factorial<10>::value);
//    LOG_INFO("sum: %d", Factorial<double>::value);

    // operator new 是 new 表达式的一部分
    Test* obj = new Test(10);
    // 等价于：
    void* raw = ::operator new(sizeof(Test));   //构建内存
    Test* obj1 = ::new(raw) Test(20);           // placement new 调构造
    obj->size();
    obj1->size();
    delete obj;
    delete obj1;
}

}
